module TB_Y86(
////////////////////	Clock Input	 	////////////////////	 
CLOCK_27,						//	27 MHz
CLOCK_50,						//	50 MHz
EXT_CLOCK,						//	External Clock
////////////////////	Push Button		////////////////////
KEY,							//	Pushbutton[3:0]
////////////////////	DPDT Switch		////////////////////
SW,								//	Toggle Switch[17:0]
///////////////////// LEDS /////////////////////////////
LEDG,
LEDR,
//////////////////// HEX Display //////////////////////
HEX0,
HEX1,
HEX2,
HEX3,
HEX4,
HEX5,
HEX6,
HEX7,
////////////////////	SRAM Interface		////////////////
SRAM_DQ,						//	SRAM Data bus 16 Bits
SRAM_ADDR,						//	SRAM Address bus 18 Bits
SRAM_UB_N,						//	SRAM High-byte Data Mask 
SRAM_LB_N,						//	SRAM Low-byte Data Mask 
SRAM_WE_N,						//	SRAM Write Enable
SRAM_CE_N,						//	SRAM Chip Enable
SRAM_OE_N						//	SRAM Output Enable
);

input CLOCK_50;
input CLOCK_27;
input EXT_CLOCK;

////////////////////////	SRAM Interface	////////////////////////
inout	[15:0]	SRAM_DQ;				//	SRAM Data bus 16 Bits
output [17:0]	SRAM_ADDR;				//	SRAM Address bus 18 Bits
output			SRAM_UB_N;				//	SRAM High-byte Data Mask
output			SRAM_LB_N;				//	SRAM Low-byte Data Mask 
output			SRAM_WE_N;				//	SRAM Write Enable
output			SRAM_CE_N;				//	SRAM Chip Enable
output			SRAM_OE_N;				//	SRAM Output Enable

input [17:0] SW;
input [4:0] KEY;

output [17:0] LEDR;
output [8:0] LEDG;

output [6:0] HEX0;
output [6:0] HEX1;
output [6:0] HEX2;
output [6:0] HEX3;
output [6:0] HEX4;
output [6:0] HEX5;
output [6:0] HEX6;
output [6:0] HEX7;

reg [31:0] addr;
wire [31:0] tmp_addr;
reg [15:0] data_i;
wire [15:0] tmp_data_i;
reg write = 0;
wire tmp_write;

wire [15:0] data_o;
wire [31:0] chip_addr;
wire [15:0] chip_data_i;
wire [15:0] chip_data_o;

wire chip_write;
wire init_ub;
wire init_lb;

reg write_data;

reg [31:0] CK;
wire RESET;
reg CLOCK;

wire [31:0] PC;
wire [7:0] INST_1_B;
wire [7:0] INST_2_B;
wire [23:0] STAGE;
wire WAIT;

//assign data_i = (!write)? addr[15:0]: 16'bz;

////////////// SRAM /////////////

//SRAM ram(.ADDR(SRAM_ADDR), .DATA(SRAM_DQ), .WE_N(SRAM_WE_N), .OE_N(SRAM_OE_N), .UB_N(SRAM_UB_N), .LB_N(SRAM_LB_N), .CE_N(SRAM_CE_N));


////////////// BUS//////////////

BUS b(.MEM_ADDR(SRAM_ADDR),
      .MEM_DATA(SRAM_DQ),
      .WE_N(SRAM_WE_N),
      .OE_N(SRAM_OE_N),
      .UB_N(SRAM_UB_N),
      .LB_N(SRAM_LB_N),
      .CE_N(SRAM_CE_N),
      .INIT_ADDR(chip_addr[17:0]),
      .INIT_DATA_IN(chip_data_o),
      .INIT_DATA_OUT(data_o),
      .INIT_WRITE(chip_write),
      .INIT_UB(init_ub),
      .INIT_LB(init_lb));
      
      
////////////////Y86/////////////



Y86 y(
		.CLOCK(CLOCK), 
		.mem_addr(chip_addr), 
		.mem_data_i(data_o), 
		.mem_write(chip_write), 
		.mem_data_o(chip_data_o),
		.reset(RESET),
		.mem_ub(init_ub),
		.mem_lb(init_lb),
		.PC_TB_o(PC),
		.INST_1_B_o(INST_1_B),
		.INST_2_B_o(INST_2_B),
		.STAGE(STAGE),
		.WAIT_o(WAIT));


always @ (PC) begin
	put(PC[15:12], HEX7);
	put(PC[11:8], HEX6);
	put(PC[7:4], HEX5);
	put(PC[3:0], HEX4);
end

always @ (INST_1_B) begin
	put(INST_1_B[7:4],HEX3);
	put(INST_1_B[3:0],HEX2);
end

always @ (INST_2_B) begin
	put(INST_2_B[7:4],HEX1);
	put(INST_2_B[3:0],HEX0);
end

assign LEDG[8] = CLOCK;
assign LEDG[7] = RESET;
assign LEDG[6] = WAIT;
assign LEDG[4] = (STAGE[3:0] == 0);
assign LEDG[3] = (STAGE[3:0] == 1);
assign LEDG[2] = (STAGE[3:0] == 2);
assign LEDG[1] = (STAGE[3:0] == 3);
assign LEDG[0] = (STAGE[3:0] == 4);

assign LEDR = SW;

assign RESET = KEY[3];

always @(posedge CLOCK_50) CK <= CK + 17'd1;

always @(SW[17:0]) begin

  casex (SW[17:0]) // synopsys parallel_case full_case
	  18'b00_0000_0000_0000_0000: CLOCK = CLOCK_50;
	  18'bxx_xxxx_xxxx_xxxx_xxx1: CLOCK = KEY[2];
	  18'bxx_xxxx_xxxx_xxxx_xx10: CLOCK = CK[0];
	  18'bxx_xxxx_xxxx_xxxx_x100: CLOCK = CK[1];
	  18'bxx_xxxx_xxxx_xxxx_1000: CLOCK = CK[2];
	  18'bxx_xxxx_xxxx_xxx1_0000: CLOCK = CK[3];
	  18'bxx_xxxx_xxxx_xx10_0000: CLOCK = CK[4];
	  18'bxx_xxxx_xxxx_x100_0000: CLOCK = CK[5];
	  18'bxx_xxxx_xxxx_1000_0000: CLOCK = CK[6];
	  18'bxx_xxxx_xxx1_0000_0000: CLOCK = CK[7];
	  18'bxx_xxxx_xx10_0000_0000: CLOCK = CK[8];
	  18'bxx_xxxx_x100_0000_0000: CLOCK = CK[9];
	  18'bxx_xxxx_1000_0000_0000: CLOCK = CK[10];
	  18'bxx_xxx1_0000_0000_0000: CLOCK = CK[11];
	  18'bxx_xx10_0000_0000_0000: CLOCK = CK[12];
	  18'bxx_x100_0000_0000_0000: CLOCK = CK[13];
	  18'bxx_1000_0000_0000_0000: CLOCK = CK[14];
	  18'bx1_0000_0000_0000_0000: CLOCK = CK[15];
	  18'b10_0000_0000_0000_0000: CLOCK = CK[23];
  endcase
end

task put;
	input a;
	output [6:0] b;
	integer a;
	begin 
		case (a)
			0: begin
				b[0] = 1'b0;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b0;
				b[4] = 1'b0;
				b[5] = 1'b0;
				b[6] = 1'b1;
			end
			1: begin 
				b[0] = 1'b1;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b1;
				b[4] = 1'b1;
				b[5] = 1'b1;
				b[6] = 1'b1;
			end
			2: begin
				b[0] = 1'b0;
				b[1] = 1'b0;
				b[2] = 1'b1;
				b[3] = 1'b0;
				b[4] = 1'b0;
				b[5] = 1'b1;
				b[6] = 1'b0;
			end
			3: begin
				b[0] = 1'b0;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b0;
				b[4] = 1'b1;
				b[5] = 1'b1;
				b[6] = 1'b0;
			end
			4: begin
				b[0] = 1'b1;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b1;
				b[4] = 1'b1;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			5: begin
				b[0] = 1'b0;
				b[1] = 1'b1;
				b[2] = 1'b0;
				b[3] = 1'b0;
				b[4] = 1'b1;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			6: begin
				b[0] = 1'b0;
				b[1] = 1'b1;
				b[2] = 1'b0;
				b[3] = 1'b0;
				b[4] = 1'b0;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			7: begin
				b[0] = 1'b0;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b1;
				b[4] = 1'b1;
				b[5] = 1'b1;
				b[6] = 1'b1;
			end
			8: begin
				b[0] = 1'b0;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b0;
				b[4] = 1'b0;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			9: begin
				b[0] = 1'b0;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b0;
				b[4] = 1'b1;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			10: begin
				b[0] = 1'b0;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b1;
				b[4] = 1'b0;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			11: begin
				b[0] = 1'b1;
				b[1] = 1'b1;
				b[2] = 1'b0;
				b[3] = 1'b0;
				b[4] = 1'b0;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			12: begin
				b[0] = 1'b0;
				b[1] = 1'b1;
				b[2] = 1'b1;
				b[3] = 1'b0;
				b[4] = 1'b0;
				b[5] = 1'b0;
				b[6] = 1'b1;
			end
			13: begin
				b[0] = 1'b1;
				b[1] = 1'b0;
				b[2] = 1'b0;
				b[3] = 1'b0;
				b[4] = 1'b0;
				b[5] = 1'b1;
				b[6] = 1'b0;
			end
			14: begin
				b[0] = 1'b0;
				b[1] = 1'b1;
				b[2] = 1'b1;
				b[3] = 1'b0;
				b[4] = 1'b0;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			15: begin
				b[0] = 1'b0;
				b[1] = 1'b1;
				b[2] = 1'b1;
				b[3] = 1'b1;
				b[4] = 1'b0;
				b[5] = 1'b0;
				b[6] = 1'b0;
			end
			default: begin
				b[0] = 1'b1;
				b[1] = 1'b1;
				b[2] = 1'b1;
				b[3] = 1'b1;
				b[4] = 1'b1;
				b[5] = 1'b1;
				b[6] = 1'b1;
			end
		endcase
	end
endtask


endmodule